package de.medieninf.android.sensimg;

import java.util.HashMap;

import android.view.KeyEvent;

public class KeyboardState {
	final static char[] ACCEPT_CHARS = {
		'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
		'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
		'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 
		'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
		',', '.', ' ', '@', '*', '#'
	};
	final static int MAX_PRESSED = 4; // no more than MAX_PRESSED keys pressed simultanuously
	
	char[] pressed;
	int nextFree;
	HashMap<Character, Character> translateChars; // allows remapping
	Object lock;
	
	public KeyboardState() {
		pressed = new char[MAX_PRESSED];
		nextFree = 0;
		lock = new Object();
		translateChars = new HashMap<Character, Character>();
		// initial mappings - for german keyboard mimic low row on normal smartphone
		translateChars.put('@', '*');
		translateChars.put(' ', '0');
		translateChars.put('.', '#');
		translateChars.put('i', 'u');
		translateChars.put('j', 'l');
		translateChars.put('k', 'r');
		translateChars.put('m', 'd');		
	}
	
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		char ch = event.getMatch(ACCEPT_CHARS, 0);
		if (ch == 0)
			return false;
		if (translateChars.containsKey(ch)) {
			ch = translateChars.get(ch);
		}
		return onKeyDown(ch);
	}

	public boolean onKeyDown(char ch) {
		if (nextFree < MAX_PRESSED) {
			synchronized (lock) {
				for (int i=0; i < nextFree; i++) {
					if (pressed[i] == ch) {
						return false; // ignore already pressed ones (key repeat)
					}
				}
				pressed[nextFree++] = ch;
			}
			return true;
		}
		return false;		
	}
	
	public boolean onKeyUp(int keyCode, KeyEvent event) {
		char ch = event.getMatch(ACCEPT_CHARS, 0);
		if (ch == 0)
			return false;
		if (translateChars.containsKey(ch)) {
			ch = translateChars.get(ch);
		}
		return onKeyUp(ch);
	}

	public boolean onKeyUp(char ch) {
		synchronized (lock) {
			for (int i=0; i<nextFree; i++) {
				if (pressed[i] == ch) {
					pressed[i] = pressed[--nextFree];
					return true;
				}
			}			
		}
		return false;
	}
	
	public String getKeys() {
		char[] data;
		
		synchronized (lock) {
			data = new char[nextFree];
			for (int i=0; i < data.length; i++)
				data[i] = pressed[i];			
		}
		return new String(data);
	}
	
	public HashMap<Character, Character> getTranslateMap() {
		return new HashMap<Character, Character>(translateChars);			
	}
	
	public void setTranslateMap(HashMap<Character, Character> translateChars) {
		HashMap<Character, Character> copy = new HashMap<Character, Character>(translateChars);
		synchronized (lock) {
			this.translateChars = copy; 
		}
	}
	
}
